package edu.maplef.bookwild.action.OAuth;

import javax.servlet.http.HttpServletRequest;

import org.apache.struts2.ServletActionContext;

import edu.maplef.bookwild.action.BaseAction;
import edu.maplef.bookwild.config.Config;
import edu.maplef.bookwild.config.Constants;
import edu.maplef.bookwild.utils.StrCharUtil;
import edu.maplef.bookwild.utils.network.HttpClient;
import edu.maplef.bookwild.utils.network.PostParameter;

/**
 * 用于用户验证的action
 * 认证流程： （1）获取Authorization Code （2）使用Authorization Code换取Access Token 
 * 参见<a href="http://wiki.dev.renren.com/wiki/%E4%BD%93%E9%AA%8C%E4%BA%BA%E4%BA%BAOAuth2.0%E9%AA%8C%E8%AF%81%E6%8E%88%E6%9D%83%E5%9F%BA%E6%9C%AC%E6%B5%81%E7%A8%8B ">校内API WIKI</a>
 * @author maple
 *
 */
public class Oauth2Action extends BaseAction {
	/**
	 * 
	 */
	private static final long serialVersionUID = 4827716451154000583L;

	private String sessionKey = null;
	private String code = null;
	private String access_token = null;
	private String client_id = Config.getConfig(Constants.XN_APIKEY);
	private int try_count = 0;
	private String GOTOURL = null;

	//action area
	/**
	 * 获取Authorization Code
	 * @throws Exception 
	 */
	public String oauth() throws Exception {

		String strCode = getParameterByName(Constants.PARAM_XN_SIG_CODE);
		String strAccessToken = getParameterByName(Constants.PARAM_XN_SIG_ACCESS_TOKEN);
		String strSessionKey = getParameterByName(Constants.PARAM_XN_SIG_SESSION_KEY);

		//如果是已授权并登陆的用户，直接转跳到
		if (!StrCharUtil.isNullOrEmpty(strSessionKey))
			return SUCCESS;

		if (strCode == null) {
			GOTOURL = buildOAuthGetCodeURL();
			return "authorize";
		} else {
			if (strCode != null && strAccessToken == null) {
				//生成参数组
				PostParameter[] params = {
						new PostParameter(Constants.PARAM_XN_SIG_CLIENT_ID,
								client_id),
						new PostParameter(Constants.PARAM_XN_SIG_CLIENT_SECRET,
								Config.getConfig(Constants.XN_SECRECT)),
						new PostParameter(
								Constants.PARAM_XN_SIG_REDIRECT_URI,
								Config
										.getConfig(Constants.XN_AUTHORIZATION_RED_URI)),
						new PostParameter(Constants.PARAM_XN_SIG_GRANT_TYPE,
								"authorization"),
						new PostParameter("code", code) };
				//接受从服务器返回的数据
				String res = hc.httpRequest(
						Config.getConfig(Constants.XN_ACCESS_TOKEN_URI),
						params, Constants.HTTP_GET).asString();
				String[] responseStr = res.split("&");
				access_token = getParameter(responseStr,
						Constants.PARAM_XN_SIG_ACCESS_TOKEN);
				if (access_token == null) {
					addActionError("get access_token failure");
					return ERROR;
				}

			}
		}
		return ERROR;
	}

	/**
	 * 处理授权
	 * @return
	 */
	public String authorize() {
		HttpServletRequest request = (HttpServletRequest) ServletActionContext
				.getRequest();

		//获取用户授权标志
		String xn_sig_added = (String) request
				.getParameter(Constants.PARAM_XN_SIG_ADDED);
		System.out.println(request.getQueryString());
		if ("1".equals(xn_sig_added)) { //用户已授权则进入应用
			return SUCCESS;
		} else { //用户未授权则引导用户授权
			return "authorize";
		}

	}

	/**
	 * 生成浏览器访问的获取code的页面地址
	 * @return
	 */
	private String buildOAuthGetCodeURL() {
		PostParameter[] params = {
				new PostParameter(Constants.PARAM_XN_SIG_CLIENT_ID, client_id),
				new PostParameter(Constants.PARAM_XN_SIG_RESPONSE_TYPE, "code"),
				new PostParameter(Constants.PARAM_XN_SIG_REDIRECT_URI, Config
						.getConfig(Constants.XN_AUTHORIZATION_RED_URI)) };
		return HttpClient.BuildUrl(Config
				.getConfig(Constants.XN_AUTHORIZATION_URI), params);
	}

	/**
	 * 从返回字符串中查找参数,没有找到返回null
	 * @param responseStr
	 * @param parameter
	 * @return
	 */
	public String getParameter(String[] responseStr, String parameter) {
		String value = null;
		for (String str : responseStr) {
			if (str.startsWith(parameter + '=')) {
				value = str.split("=")[1].trim();
				break;
			}
		}
		return value;
	}

	public String getSessionKey() {
		return sessionKey;
	}

	public void setSessionKey(String sessionKey) {
		this.sessionKey = sessionKey;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getCode() {
		return code;
	}

	public String getClient_id() {
		return client_id;
	}

	public void setClient_id(String clientId) {
		client_id = clientId;
	}

	public int getTry_count() {
		return try_count;
	}

	public void setTry_count(int tryCount) {
		try_count = tryCount;
	}

	public String getGoToURL() {
		return GOTOURL;
	}

	public void setGoToURL(String goToURL) {
		GOTOURL = goToURL;
	}
}
